import { v4 as uuidv4 } from 'uuid'
import { reactive, computed, ref } from 'vue'
import chatMgr from './chat-manager'
import agentMgr from './ai-agent'
import {
  type AIAgent,
  type ChatMessage,
  AIGCStatus,
  MessageType,
  type MessageContent,
  type IMessageParser,
  MessageContentType
} from './interface'
import { startAIGC, fetchAIGCContent } from '@/utils/api'

import { IFlyParser } from './ifly-parser'
import { ElMessage } from 'element-plus'
// //EventStream Import
// import { fetchEventSource } from '@microsoft/fetch-event-source'
// import { useAuthStore } from '../stores/auth'

// class RetriableError extends Error {}
// class FatalError extends Error {}

export class AIGCSession {
  readonly agent: AIAgent
  readonly conversionId: string
  readonly isLocal: boolean = false //
  taskId?: string = '' //
  private sessionId?: string

  private _handleMessageRef = ref<ChatMessage>() // 正在生成的消息
  public status: any = ref(AIGCStatus.Idle) // 生成消息状态

  private _callback?: (delegate: any, data: ChatMessage[]) => void //将上次回答完成的消息推出给 chat-session 列表归档
  public question?: any //发起的问题

  private messageParser: IMessageParser = new IFlyParser()

  currentAIGCContent?: {} //生成式对话消息服务端已返回的数据

  private _askMessage: ChatMessage[] = []
  private _replyMessage: ChatMessage[] = [] //暂时没有回复的消息

  private aigcMessageId: string = uuidv4()
  private aigcReplyMessageContents: MessageContent[] = [] //单一消息，多个内容组成

  private state = reactive({
    _askMessage: this._askMessage,
    _replyMessage: this._replyMessage
  })

  private delegateController: any

  private replyErrorCounter = 0

  public messageList: ChatMessage[] = computed(() => [
    ...this.state._askMessage,
    ...this.state._replyMessage
  ])

  public get handleMessage(): ChatMessage | undefined {
    return this._handleMessageRef.value
  }

  public addAskMessage(message: ChatMessage): void {
    this.state._askMessage.push(message)
  }

  // 构造函数定义
  constructor(
    agent: AIAgent,
    conversionId: string,
    isLocal: boolean = false, // 设置默认值,
    delegate: any,
    callback: (delegate: any, data: ChatMessage[]) => void
  ) {
    this.agent = agent
    this.conversionId = conversionId
    this.isLocal = isLocal
    this._callback = callback
    this.delegateController = delegate
    if (!isLocal) {
      this.sessionId = conversionId
    }
  }

  public ask(quesition: any): void {
    this.question = quesition
    //将上次对话归档到chasession
    if (this._callback) {
      if (this.handleMessage) {
        this._callback(this.delegateController, [
          ...this.state._askMessage,
          ...this.state._replyMessage,
          this.handleMessage
        ])
        console.log('==========将上次对话归档到chasession', [
          ...this.state._askMessage,
          ...this.state._replyMessage,
          this.handleMessage
        ])
      }
    }
    this.startAsk()
  }

  public reAsk(): void {
    this.startAsk()
  }

  public cancel(): void {
    if (this.status.value === AIGCStatus.Started || this.status.value === AIGCStatus.InProgress) {
      this.status.value = AIGCStatus.Canceled
    }
    this.stopPolling()
  }
  startAsk(): void {
    this.reset()
    this.status.value = AIGCStatus.Started
    const content: MessageContent = {
      content: this.question,
      contentType: MessageContentType.Text,
      rowData: {}
    }

    const msg: ChatMessage = {
      messageId: uuidv4(),
      messageType: MessageType.Text,
      contentList: [content],
      isSend: true,
      status: 'Sending'
    }

    this.addAskMessage(msg)
    console.log('==========开始新问题', this.question)
    this.getTaskIdFromServer()
  }

  reset() {
    this.taskId = ''
    this.aigcMessageId = uuidv4()
    this.state._askMessage = []
    this.state._replyMessage = []
    this._handleMessageRef.value = undefined
    this.status.value = AIGCStatus.Idle
    this.replyErrorCounter = 0
    this.cachedData = ''
    this.displayData = ''
  }

  async getTaskIdFromServer(): Promise<void> {
    try {
      const param: Record<string, any> = { content: this.question, agent_id: this.agent.id }
      if (this.sessionId) {
        //非新对话，会携带会话Id初始，新会话，第一次回答后会赋值远端会话Id
        param.session_id = this.sessionId
      }
      // console.log('getTaskIdFromServer:', param)

      const data = await startAIGC(param)
      this.taskId = data.task_id
      console.log('==========开始回答', this.taskId, this.question)
      this.startPolling()
    } catch (err) {
      console.log('getTaskIdFromServer ERROR:', err)
      this.handleAIGCError(err)
    }
  }

  handleAIGCError(err: any) {
    this.replyErrorCounter++
    console.log('handleAIGCError:', this.replyErrorCounter, err)

    if (this.replyErrorCounter > 5) {
      ElMessage.error('获取数据失败，请稍后再试')
      this.status.value = AIGCStatus.Error
      this.stopPolling()
    }
  }

  //轮询
  displayData: string = ''
  cachedData: string = ''
  isPolling: boolean = false
  isTypewriterRunning: boolean = false

  pollInterval: NodeJS.Timeout | null = null
  typewriterInterval: NodeJS.Timeout | null = null

  // 开始轮询
  startPolling() {
    if (!this.isPolling) {
      this.isPolling = true
      console.log('startPolling')

      this.pollInterval = setInterval(() => {
        this.fetchAIGCData()
      }, 1000)
    }

    if (!this.isTypewriterRunning) {
      this.typewriterInterval = setInterval(() => {
        //TODO: 当displayData 小于 cachedData 长度时
        if (this.currentAIGCContent && this.displayData.length < this.cachedData.length) {
          const displayData = this.cachedData.slice(0, this.displayData.length + 1)
          this.updateDisplayData(displayData)
        }
      }, 30)
      this.isTypewriterRunning = true
    }
  }

  // 停止轮询
  stopPolling() {
    if (this.pollInterval) {
      console.log('stopPolling')

      clearInterval(this.pollInterval)
      this.pollInterval = null
      this.isPolling = false
    }

    //停止模拟display 输出，一次性全部输出
    if (this.cachedData && this.cachedData !== this.displayData) {
      this.displayData = this.cachedData
      this.updateDisplayData(this.displayData)
    }
    if (this.typewriterInterval) {
      console.log('stopDisplayInterval')

      clearInterval(this.typewriterInterval)
      this.typewriterInterval = null
      this.isTypewriterRunning = false
    }

    //更新 我的智能体和会话历史
    chatMgr.getChatHistory()
    agentMgr.getMyAIAgents()
  }

  async fetchAIGCData() {
    try {
      const data = await fetchAIGCContent({ task_id: this.taskId })
      if (!data?.replay_data?.payload?.choices) {
        // ElMessage.error('获取数据失败，请稍后再试')
        // this.stopPolling()
        this.handleAIGCError(new Error('获取数据失败，请稍后再试'))
        return
      }
      const taskStatus: AIGCStatus = this.messageParser.taskStatusFromResp(data)
      if (!this.sessionId) {
        this.sessionId = this.messageParser.sessionIdFromResp(data)

        setTimeout(() => {
          chatMgr.getChatHistory()
          agentMgr.getMyAIAgents()
        }, 1000)
      }
      //过滤不支持的消息内容
      const contents: any[] = this.messageParser
        .contentRowDataListFromResp(data)
        .filter((rowData) => {
          return this.messageParser.isSupportedContentType(rowData)
        })

      //已经回答的内容
      if (contents.length > 1) {
        const replays: MessageContent[] = contents.slice(0, -1).map((rowData) => {
          const content: MessageContent = this.messageParser.messageContentWithRowData(rowData)
          return content
        })
        this.aigcReplyMessageContents = replays
      }
      //正在回答的内容
      if (taskStatus === AIGCStatus.Completed || taskStatus === AIGCStatus.InProgress) {
        this.currentAIGCContent = contents[contents.length - 1]
        console.log('==========回答进行中', this.taskId)
        //需要以打字机模式输出
        if (this.messageParser.isTypeWriterContent(this.currentAIGCContent)) {
          // console.log('需要以打字机模式输出:', this.currentAIGCContent)
          this.cachedData = this.messageParser.aigcTypeWriterContentCacheData(
            this.currentAIGCContent
          )
        } else {
          //无需打字机模式输出,直接添加到 已经回答的内容列表
          // console.log('无需打字机模式输出:', this.currentAIGCContent)
          if (this.messageParser.isSupportedContentType(this.currentAIGCContent)) {
            const msgContent = this.messageParser.messageContentWithRowData(this.currentAIGCContent)
            this.aigcReplyMessageContents.push(msgContent)
          }
          this.cachedData = ''
        }

        this.handleDisplayData(taskStatus)
      }

      if (taskStatus === AIGCStatus.Completed) {
        console.log('==========回答完成', this.taskId, taskStatus, this.question)

        this.stopPolling()
      }
      this.status.value = taskStatus
    } catch (error) {
      console.error('Error fetching data:', error)
      //数据拉取错误时 重试几次，然后停止轮询
      this.handleAIGCError(error)
    }
  }

  handleDisplayData(status: AIGCStatus) {
    // console.log('cachedData', this.typewriterInterval, this.cachedData)
    if (!this.cachedData) {
      //不需要打字机模式输出
      this.updateDisplayData('')
    }
  }

  updateDisplayData(content: string) {
    if (content) {
      //打字机模式
      this.displayData = content
      const rowData = { ...this.currentAIGCContent }
      rowData.content = this.displayData

      const msgContent = this.messageParser.messageContentWithRowData(rowData)

      const msg: ChatMessage = {
        messageId: this.aigcMessageId,
        messageType: MessageType.Text,
        contentList: [...this.aigcReplyMessageContents, msgContent], //加上打字机模式内容
        isSend: false
      }
      this._handleMessageRef.value = msg
      // console.log(
      //   'updateDisplayData Type Writer:',
      //   this.aigcReplyMessageContents.length,
      //   msgContent.content
      // )
    } else {
      //非打字机模式
      const msg: ChatMessage = {
        messageId: this.aigcMessageId,
        messageType: MessageType.Text,
        contentList: [...this.aigcReplyMessageContents], //返回已返回数据
        isSend: false
      }
      this._handleMessageRef.value = msg
      // console.log(
      //   'updateDisplayData All:',
      //   this.aigcReplyMessageContents.length,
      //   this.handleMessage
      // )
    }
  }

  // messageFormat(data: MessageContent): ChatMessage {
  //   const dataCopy = { ...data }
  //   if (dataCopy.content_type === 'text') {
  //     //TODO: markdown 解析
  //     dataCopy.content = parseMarkdownToHTML(escapeHTML(processContent(data.content)))
  //   }

  //   const message: ChatMessage = {
  //     messageId: uuidv4(),
  //     msgContent: dataCopy,
  //     messageType: data.content_type,
  //     isSend: data.role !== 'assistant'
  //   }
  //   return message
  // }

  // //EventStream
  // fetchEventGpt = (data: any, callData: (arg0: any) => void) => {
  //   const ctrl = new AbortController()

  //   const { getToken } = useAuthStore()
  //   const token = getToken() // 从 authStore 中获取 token

  //   console.log('sse start with:', data)

  //   fetchEventSource('/apis/api/agent/chat/test_stream', {
  //     method: 'POST',
  //     headers: {
  //       'Content-Type': 'application/json',
  //       Authorization: `${token}`
  //     },
  //     body: JSON.stringify(data),
  //     signal: ctrl.signal,
  //     openWhenHidden: true,
  //     async onopen(response: any) {
  //       // 成功连接时回调
  //       console.log('sse onopen resp:', response)

  //       if (
  //         response.ok &&
  //         (response.headers.get('content-type') as string) === 'text/event-stream; charset=utf-8'
  //       ) {
  //         return // everything's good
  //       } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
  //         // client-side errors are usually non-retriable:
  //         console.log('sse onopen FatalError:', response)
  //         throw new FatalError()
  //       } else {
  //         console.log('sse onopen RetriableError:', response)
  //         throw new RetriableError()
  //       }
  //     },
  //     onmessage(msg: { data: any; event: string }) {
  //       // 服务器返回消息回调 返回{ data,event,id,retry } ，data即服务器返回数据
  //       // if the server emits an error message, throw an exception
  //       // so it gets handled by the onerror callback below:
  //       console.log('sse onmessage msg:', msg)
  //       if (msg.event === 'FatalError') {
  //         console.log('sse onmessage FatalError:', msg)
  //         throw new FatalError(msg.data)
  //       }

  //       if (msg.event == '') {
  //         // 进行连接正常的操作
  //         try {
  //           // const data = JSON.parse(msg.data) ?? {}
  //           const data = msg.data
  //           console.log('data:', data)

  //           const { finish, code } = data ?? {}
  //           callData(data)
  //           if (code * 1 === 200 && finish) {
  //             ctrl.abort()
  //           }
  //         } catch (err) {
  //           console.log('sse onmessage dataError:', err, msg)
  //           throw err
  //         }
  //       }

  //       if (msg.event === 'close') {
  //         ctrl.abort()
  //       }
  //     },
  //     onclose() {
  //       // 正常结束的回调
  //       ctrl?.abort()
  //       console.log('sse onclose RetriableError')
  //       throw new RetriableError()
  //     },
  //     onerror(err: any) {
  //       // 连接出现异常回调
  //       // 必须抛出错误才会停止
  //       console.log('sse onerror:', err)
  //       ctrl?.abort()
  //       if (err instanceof FatalError) {
  //         throw err // rethrow to stop the operation
  //       } else {
  //         // do nothing to automatically retry. You can also
  //         // return a specific retry interval here.
  //         throw err
  //       }
  //     }
  //   })
  // }
}
